<?xml version="1.0" encoding="UTF-8"?>
<html>
    <head>
        <link type="text/css" rel="stylesheet" href="./css/template.css" />
        <link type="text/css" rel="stylesheet" href="./css/SyntaxHighlighter.css" />
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Objet ThreadLocal</title>
        <script language="javascript" src="./js/shInit.js" />
        <script language="javascript" src="./js/shCore.js" />
        <script language="javascript" src="./js/shBrushCpp.js" />
        <script language="javascript" src="./js/shBrushCSharp.js" />
        <script language="javascript" src="./js/shBrushCss.js" />
        <script language="javascript" src="./js/shBrushDelphi.js" />
        <script language="javascript" src="./js/shBrushJava.js" />
        <script language="javascript" src="./js/shBrushJScript.js" />
        <script language="javascript" src="./js/shBrushPhp.js" />
        <script language="javascript" src="./js/shBrushPython.js" />
        <script language="javascript" src="./js/shBrushRuby.js" />
        <script language="javascript" src="./js/shBrushSql.js" />
        <script language="javascript" src="./js/shBrushVb.js" />
        <script language="javascript" src="./js/shBrushXml.js" />
        <keywords>Objet ThreadLocal</keywords>
        <author>Michel PIRES</author>
    </head>
    <body>
        <div class="chapter">
            <h2>Objet ThreadLocal</h2>
        </div>
        <div class="chapter">
            <h2>1. Introduction</h2>
            <p>Fin 1998, Sun lançait le JDK 1.2. Elle apportait alors de nombreuses nouveautés, dont celle à laquelle nous nous intéresserons ici. La classe ThreadLocal.</p>
            <p>Cette classe se révèle très utile pour simplifier le développement de programmes multi-threads concurrent.</p>
            <p>Pour illustrer cela, disons que vous voulez créer une application mutli-thread utilisant une même instance. En utilisant un champ statique, celui-ci pourra être utilisé dans tout les processus, mais non modifiable. En utilisant un champ non statique, celui-ci pourra être modifié dans n’importe quel processus, ce qui n’est pas forcément une bonne idée.</p>
            <p>Pour cela, ThreadLocal peut nous simplifier la vie, en effet il nous permet de créer une variable propre à chaque Thread. L’objet ThreadLocal stocke une valeur qui n’est accessible que par le thread courant. Les autres threads n’ont pas accès à cet objet.</p>
            <h2>2. Description</h2>
            <div class="subChapter">
                <h3>2.1 Générale</h3>
                <h4>Constructeur :</h4>
                <textarea name="code" class="java">ThreadLocal() ;</textarea>
                <p>Construit un nouvel objet ThreadLocal.</p>
                <h4>Méthodes :</h4>
                <textarea name="code" class="java">protected Object initialValue()</textarea>
                <p>Retourne la valeur initiale du Thread courant pour cette variable ThreadLocal.</p>
                <textarea name="code" class="java">void set(Object T)</textarea>
                <p>Fixe la copie du Thread courant de cette variable ThreadLocal à la valeur indiquée.</p>
                <textarea name="code" class="java">Object get()</textarea>
                <p>Retourne la valeur dans la copie du Thread courant de la variable ThreadLocal.</p>
                <textarea name="code" class="java">void remove()</textarea>
                <p>Efface la valeur pour ce ThreadLocal.</p>
                <h4>Méthodes héritées de la classe java.lang.Object :</h4>
                <p>Clone(), equals(java.lang.Object), finalize(), getClass(), hashCode(), notify(), notifyAll(), toString(), wait(), wait(long), wait(long, int).</p>
            </div>
            <div class="subChapter">
                <h3>2.2. Details des méthodes</h3>
                <h4>protected Object initialValue()</h4>
                <p>A défaut de méthode set(Object T) implémenter, cette méthode est appelé au plus une fois pour chaque thread créer lors du premier get().</p>
                <p>Par défaut, initialValue() retourne simplement null, mais son comportement peut être redéfini.</p>
                <p>Exemple :</p>
                <textarea name="code" class="java">//On redéfinie le comportement de initialValue()
					class monThreadLocal extends ThreadLocal{
					protected Object initialValue() {
					return (String) "Je suis une valeur initiale";
					// Il renvoie un chaîne de caractère
					}
					}
					class AvecThreadLocal implements Runnable {
					public monThreadLocal Tl= new monThreadLocal();
					public void run() {
					System.out.println(" ThreadLocal = "+Tl.get());
					}
					}
					public class Main {
					public static void main(String[] args) {
					Thread T1 = new Thread(new AvecThreadLocal());
					T1.start();
					}
					}
					//sortie :
					ThreadLocal = Je suis une valeur initiale
					// L’objet de ThreadLocal a pris pour valeur celle que lui a renvoyer initialValue()</textarea>
                <h4>Object get()</h4>
                <p>Cette méthode nous retourne la valeur contenue dans l’objet ThreadLocal an.</p>
                <p>Lors du premier appelle de get(), et si set() n’a pas été invoquer précédemment par ce Thread, la méthode initialValue() est appelé afin d’établir une valeur par défaut.</p>
                <p>Voir les exemples précédents.</p>
                <h4>void remove()</h4>
                <p>Cette méthode permet d’effacer la valeur du ThreadLocal.</p>
                <p>Si l’on désire a nouveau accéder a la valeur de ce thread, à défaut d’une méthode set(), on aura en retour un objet null, retourner par la méthode initialValue().</p>
                <p>Exemple :</p>
                <textarea name="code" class="java">class AvecThreadLocal implements Runnable {
					public ThreadLocal Tl= new ThreadLocal();
					public void run() {
					Tl.set("Utilisateur a utilisé set()");
					System.out.println("Avant Remove: ThreadLocal = "+Tl.get());
					Tl.remove();
					System.out.println("Après Remove: ThreadLocal = "+Tl.get());
					}
					}
					public class Main {
					public static void main(String[] args) {
					Thread T1 = new Thread(new AvecThreadLocal());
					T1.start();
					}
					}
					//Sortie:
					Avant Remove: ThreadLocal = Utilisateur a utilisé set()
					Après Remove: ThreadLocal = null
					//La méthode remove() a supprimer le contenu de l’objet de ThreadLocal.
					//Au moment de l’impression, l’appel a get() nous renvoi null, car un appel a initialValue, non
					// implémenté ici, a été fait.</textarea>
                <h4>void set(Object T)</h4>
                <p>Cette méthode nous permet de fixer la valeur détenue dans l’objet ThreadLocal.</p>
                <p>Celle-ci est liée au thread courant et seulement pour lui.</p>
                <textarea name="code" class="java">// On attribue nous même une valeur a l’objet contenu dans ThreadLocal par la méthode set().
					class AvecThreadLocal implements Runnable {
					public ThreadLocal Tl= new ThreadLocal();
					public void run() {
					Tl.set("Utilisateur a utilisé set()");
					System.out.println(" ThreadLocal = "+Tl.get());
					}
					}
					public class Main {
					public static void main(String[] args) {
					Thread T1 = new Thread(new AvecThreadLocal());
					T1.start();
					}
					}
					//sortie :
					ThreadLocal = Utilisateur a utilisé set()
					// L’objet de ThreadLocal a pris pour valeur celle qu’on lui a attribuée.</textarea>
                <h4>Object get()</h4>
                <p>Cette méthode nous retourne la valeur contenue dans l’objet ThreadLocal an.</p>
                <p>Lors du premier appelle de get(), et si set() n’a pas été invoquer précédemment par ce Thread, la méthode initialValue() est appelé afin d’établir une valeur par défaut.</p>
                <p>Voir les exemples précédents.</p>
                <h4>void remove()</h4>
                <p>Cette méthode permet d’effacer la valeur du ThreadLocal.</p>
                <p>Si l’on désire a nouveau accéder a la valeur de ce thread, à défaut d’une méthode set(), on aura en retour un objet null, retourner par la méthode initialValue().</p>
                <p>Exemple :</p>
                <textarea name="code" class="java">class AvecThreadLocal implements Runnable {
					public ThreadLocal Tl= new ThreadLocal();
					public void run() {
					Tl.set("Utilisateur a utilisé set()");
					System.out.println("Avant Remove: ThreadLocal = "+Tl.get());
					Tl.remove();
					System.out.println("Après Remove: ThreadLocal = "+Tl.get());
					}
					}
					public class Main {
					public static void main(String[] args) {
					Thread T1 = new Thread(new AvecThreadLocal());
					T1.start();
					}
					}
					//Sortie:
					Avant Remove: ThreadLocal = Utilisateur a utilisé set()
					Après Remove: ThreadLocal = null
					//La méthode remove() a supprimer le contenu de l’objet de ThreadLocal.
					//Au moment de l’impression, l’appel a get() nous renvoi null, car un appel a initialValue, non
					// implémenté ici, a été fait.</textarea>
                <h2>3. Remarque</h2>
                <p>Il est aussi nécessaire de remarquer que le ThreadLocal n’existe que lorsque le Thread est vivant.
					Un exemple viendra illustrer cela.</p>
                <h2>4. Utilisation</h2>
                <p>Comme bien souvent, un petit exemple nous permet de bien comprendre le fonctionnement de ThreadLocal.</p>
                <p>Exemple 1 :</p>
                <textarea name="code" class="java">class AvecThreadLocal implements Runnable {
					public ThreadLocal Tloc;
					public Object o;
					public AvecThreadLocal () {  // Constructeur de notre AvecThreadLocal
					Tloc = new ThreadLocal();
					o = new String ();
					}
					public void dormir(){
					try {    Thread.sleep(1000);
					} catch (InterruptedException e) {     e.printStackTrace();    }
					}
					public void run() {
					String name = Thread.currentThread().getName();
					Tloc.set("Local_"+name);  // on attribut la même valeur a l’objet de ThreadLocal et
					o = "Objet_"+name;       // à l’objet o.
					System.out.println("Avant attente ---NOM="+ name
					+"\n      ThreadLocal="+Tloc.get()
					+"      Objet="+ o);
					dormir();      //  On met en attente le Thread courant
					System.out.println("Après le dodo ---NOM="+ name
					+"\n      ThreadLocal="+Tloc.get()
					+"      Objet="+ o);
					}
					}
					public class Main {
					public static void main(String[] args) {
					AvecThreadLocal tl = new AvecThreadLocal();
					// on creer une instance AvecThreadLocal;
					Thread T0 = new Thread(tl); // Creation du Thread T1
					Thread T1 = new Thread(tl); //
					T0.start();
					T1.start();
					try {
					T0.join();
					T1.join();
					System.out.println("\n Dans le Main: \nThreadLocal= "+tl.Tloc.get()+ " &amp; \nObjet= " + tl.o);
					} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					}
					}
					}
					Sortie :
					Avant attente ---NOM=Thread-0
					ThreadLocal=Local_Thread-0      Objet=Objet_Thread-0
					Avant attente ---NOM=Thread-1
					ThreadLocal=Local_Thread-1     Objet=Objet_Thread-1
					Après le dodo ---NOM=Thread-0
					ThreadLocal=Local_Thread-0      Objet=Objet_Thread-1
					Après le dodo ---NOM=Thread-1
					ThreadLocal=Local_Thread-1      Objet=Objet_Thread-1
					Dans le Main:
					ThreadLocal= null &amp;
					Objet= Objet_Thread-1</textarea>
                <p>Remarqué bien ce que nous renvoie ce programme.
					La valeur de l’objet de ThreadLocal , contrairement a l’objet « simple », n’a pas été modifiée pendant l’attente.</p>
                <p>En effet, le ThreadLocal est exclusif au Thread courant.</p>
                <p>Contrairement aux autres objet, ou tout les Threads se le partage, et y ont donc accès.</p>
                <p>De plus, après exécution des Threads, la valeur du ThreadLocal est null. Ceci est dû au fait que le ThreadLocal n’existe que pendant qu’ils sont actifs.</p>
                <h2>5. Conclusion</h2>
                <p>Comme nous venons de le voir, cette classe peut être d’une utilité certaine.</p>
                <p>Elle simplifie la programmation au niveau des threads, nous permettant d’utiliser à la fois des objets utilisables par tout les threads, et des objets exclusif au thread courant grâce à ThreadLocal.</p>
                <p>A vous de jouer.</p>
            </div>
        </div>
    </body>
</html>

